Skip to content

feat(libinput): 让输入链的顶端第一次真的被编译 - #298

Merged
Sunrisepeak merged 4 commits into
mainfrom
feat/libinput-test-member
Aug 30, 2026
Merged

feat(libinput): 让输入链的顶端第一次真的被编译#298
Sunrisepeak merged 4 commits into
mainfrom
feat/libinput-test-member

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

compat.libinput#294 进了索引,而它从未被编译过 —— 没有测试成员消费它,而没人编译的包不会编译失败。

加上 tests/examples/libinput 之后,一次构建暴露四类问题,都源自"上游用 meson,我们不用":

# 问题 症状落点
1 libinput-version.h(meson 从 .h.in 生成) libinput-private.h:45 无条件 include,40 个源文件全挂
2 config.h 只写了一半 HTTP_DOC_LINK / LIBINPUT_QUIRKS_OVERRIDE_FILE / LIBINPUT_PLUGIN_{LIB,ETC}DIR / HAVE_VERSIONSORT / HAVE_MTDEV
3 include_dirs 少了包根 全树只有一个文件写 #include "src/evdev-frame.h"
4 typeof 是 GNU 关键字 -std=c11 下 cast 塌成 int,错误落在十几个没提 typeof 的文件里

两个值得单独说的:

HAVE_VERSIONSORT —— 不定义它,libinput-versionsort.h 会给出自己的 static strverscmp,而 glibc 已经 extern 声明过。这是硬错误,不是遮蔽。

c_standard = "gnu11" 不是 typeof 的解法 —— mcpp 收下这个字符串,仍然发 -std=c11。这次是实测的:设过 gnu11,那些错误原样还在。所以走 -Dtypeof=__typeof__,并把这件事写进描述符注释,免得下一个人再试一遍。

测试成员

断言的是四包交接处(libudev 起 context → udev 枚举 seat → dispatch → 可 poll 的 fd),不断言能打开 /dev/input/event* —— 那需要权限,MCPP_RUN_INPUT_DEVICES=1 才要求。

the process has a dynamic linker (trivially)               ok
libudev: udev_new (compat.libudev)                         ok
libinput_udev_create_context on it                         ok
   libinput_udev_assign_seat("seat0") = 0
libinput enumerated the seat through libudev               ok
libinput_dispatch with nothing pending                     ok
   epoll fd: 3
libinput_get_fd returns a pollable descriptor              ok
   drained 0 event(s), 0 device(s) opened
the event queue drained without blocking                   ok

没有 [indices],是故意的:成员级 [indices] 是替换不是合并,一个路径只能注册在一个 namespace 下,所以在这里声明 freedesktop 会让 compat.libinput 反过来去已发布索引里找。继承根的 compat = { path = "." } 才对 —— compat 来自 checkout,freedesktop.libevdev 来自已发布索引(它确实已发布)。

顺带

  • 把 quirks 那段注释改准:LIBINPUT_QUIRKS_DIR 是有环境变量出口的(libinput.c:1911),和 GBM_BACKENDS_PATH 同一形状 —— 缺的是提供方,不是机制。运行时那条 failed to find data files 是优雅降级:枚举/事件/手势都正常,丢的是逐机型调校。
  • tests/examples/libxkbcommon 补 RMLVO 一节:XKB_CONFIG_ROOT 未设置时只报告,设置了才要求 xkb_keymap_new_from_names(evdev/pc105/us) 编得出来。为 xim 侧的 xkeyboard-config 数据包留的接口。

compat.libinput 随 #294 进了索引,而它从未被编译过——没有测试成员消费它,
而没人编译的包不会编译失败。加上 tests/examples/libinput 之后一次构建暴露出
四类问题,都是"上游用 meson,我们不用"才会有的:

1. 缺 libinput-version.h。meson 从 .h.in 生成,libinput-private.h:45 无条件
   include 它,所以 40 个源文件全挂。补成 generated_files。

2. config.h 只写了一半。HTTP_DOC_LINK / LIBINPUT_QUIRKS_OVERRIDE_FILE /
   LIBINPUT_PLUGIN_{LIB,ETC}DIR / HAVE_VERSIONSORT / HAVE_MTDEV 都缺。
   HAVE_VERSIONSORT 尤其关键:不定义它,libinput-versionsort.h 会给出自己的
   static strverscmp,而 glibc 已经 extern 声明过——是硬错误不是遮蔽。

3. include_dirs 少了包根。全树只有 libinput-plugin-mouse-wheel-lowres.c:31
   写 `#include "src/evdev-frame.h"`,上游因为从项目根编译而免费拿到这个拼法。

4. typeof。util-mem.h:180 的 (typeof(*ptr_))_steal(ptr_) 是 GNU 关键字,
   -std=c11 下被当成未声明函数调用,cast 塌成 int,伤害落在十几个根本没提
   typeof 的文件里,报成 -Wint-conversion。

   c_standard = "gnu11" 不是解法:mcpp 收下这个字符串,仍然发 -std=c11。
   这次是实测的——设过 gnu11,上面这些错误原样还在。所以走 -Dtypeof=__typeof__。

测试成员断言的是四包交接处(libudev 起 context、udev 枚举 seat、dispatch、
可 poll 的 fd),不断言能打开 /dev/input/event*——那需要权限,设
MCPP_RUN_INPUT_DEVICES=1 才要求。6 项全过。

顺带把 quirks 那段注释改准:LIBINPUT_QUIRKS_DIR 是有环境变量出口的
(libinput.c:1911),和 GBM_BACKENDS_PATH 同一形状,缺的是提供方而不是机制。
§10.9.1 xkeyboard-config 已落地(xim-pkgindex#732),含实现中改的两处 discovery
形状:XKB_CONFIG_ROOT 是标量所以用 op=set(表里第一个非列表项),以及
declare_xkb —— 声明变量和放置内容是两件事,只声明的那一版让变量指向不存在的目录。

§10.9.2 新增:libinput quirks 是同一形状的第三处。之前注释里写的「编译期路径」
不准确,libinput.c:1911 是 getenv 优先。所以不是死路,是缺提供方。

§10.10 G5 从「待接上」改为已做,并把测试成员抓出的四个 bug 列出来——它们全都是
「包进了索引但从没被编译过」造成的。另加一张发现变量总表,标出哪两行仍是空的。
c_standard 从 gnu11 改回 c11 之后,config.h 里 HAVE_C23_AUTO 那段还写着
「builds as gnu11」。

以及 config.h 顶部对 LIBINPUT_QUIRKS_DIR 的说明还停在「编译期路径」,
与文件头已改准的版本不一致——libinput.c:1911 是 getenv 优先、编译期值兜底。
合并 xim#732 后又从「已发布索引 + 全新 subos + 沙箱」复验一遍——上一次用的是
--add-xpkg 的本地副本,证明力不同。

第一次复验数据没放进去,差点得出「包坏了」。真因是 store 里还留着本地验证时的
local:xkeyboard-config@2.48,而 store 查找忽略 namespace,(name, version) 撞上
就把 install() 静默跳过、payload 为空,config() 照常跑。

顺带记下:declare_xkb 的 os.isdir 守卫确实触发了,但那条 log.warn 在 install
输出里没出现(同一次输出里 xlings 自己的 [warn] 是打出来的)。所以 declare_dri /
declare_gbm / declare_xkb 的警告都不能当诊断依赖。
@Sunrisepeak
Sunrisepeak merged commit af79fd2 into main Aug 30, 2026
11 checks passed
@Sunrisepeak
Sunrisepeak deleted the feat/libinput-test-member branch August 30, 2026 11:26
Sunrisepeak added a commit that referenced this pull request Aug 30, 2026
设计文档此前停在 #734,漏掉最后两个 PR,而它们恰好含本轮最可迁移的发现。

§11.1 完整变更集:八个 PR 两个仓,标出哪三个是回归修复。

§11.2 为什么不是单 PR。两条是硬约束、一条是我的失误,分开写:
  - 跨仓:一个 PR 无法跨两个 GitHub 仓库,而 §10.9 已论证这个切分是两个索引
    各做各建模的事;
  - 发布顺序:#301 的脚本从**已发布索引**解析 compat.libinput,只能在 #298
    合入并发布产物之后才可能被验证;
  - #733/#735 本可以不存在——它们修的是 #732 的回归,靠自我 review 而非新信息
    找到,所以合 #732 之前跑完检查清单就都在 #732 里了。清单是被这两次回归逼
    出来的,代价就是规则从事故里学、而事故已进历史。

§11.3 libs/** 三处缺席:前两处漏评审覆盖,第三处漏**交付**——#735 合了全绿、
镜像同步到位,xlings update 仍在发修复前那一版。这解释了本轮四处问题为什么
全部靠自我 review 发现、没有一处是 CI 抓到的。

§11.4 加一行 DISCOVERY = 三项检查,两项分别被 #733/#735 逼出来。

§11.5 最终状态,含用户侧产物核验(xim-index-ea36f6b.tar.gz)与两份数据归档
的双镜像 sha256 一致性。

头部状态从「待 review」改为「已实现并闭环验证(v1.0)」。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant